﻿using System;
using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json;

/*
/// 基本思想如下，在数值运算时，直接long和long 之间的运算，
/// 如果比如long和float运算，那么用函数Parse转换为long再运算，
/// 这种效率相对Fix64那种方法速度更快，并且具备可读性，
/// 在这里应该严格控制逻辑的输入和运算都是long（int64），
/// 只有在输出需要其他数据类型才转换，比如UI显示，输出到unity。。。
/// 在这个简易的定点数算法里面，非常容易溢出，
/// 原因在于用于表示小数部分的数字在参与进来的时候容易溢出，相同的数量级的数子，
/// 之所以float不会溢出是因为其用的科学计数法，而这个简易的并没有用科学计数法来表示。
*/
class Decimal
{
    public const long MaxValue = long.MaxValue;
    public const long MinValue = long.MinValue;

    //转换规则，用大精度转换为小精度，比如float就用double来转换
    //对于乘除来说， 他们之间并不能直接相除 long_a*long_a / split_xxx  才是真正的结果 
    public const long SPLIT_LONG = 100000;
    public const int SPLIT_INT = 100000;
    public const float SPLIT_FLOAT = 100000.0f;
    public const double SPLIT_DOUBLE = 100000.0;
    [JsonProperty]
    public long value;
    public Decimal(Decimal other)
    {
        this.value = other.value;
        Decimal a=new Decimal(10.5), b=new Decimal(12);
    }
    public Decimal(long value)
    {
        this.value = value;// 默认构造不认为是定点 需要手动调用parse
    }
    public Decimal(double value)
    {
        this.value = Parse(value);
    }
    public Decimal(float value)
    {
        this.value = Parse(value);
    }
    public Decimal(int value)
    {
        this.value = Parse(value);
    }
    public static implicit operator Decimal(float value)
    {
        return new Decimal(value);
    }
    public static implicit operator Decimal(double value)
    {
        return new Decimal(value);
    }
    public static implicit operator Decimal(int value)
    {
        return new Decimal(value);
    }
    public static implicit operator Decimal(long value)
    {
        return new Decimal(value);
    }
    public static long Parse(float v)
    {
        double tmp = v;
        return (long)(tmp * SPLIT_DOUBLE);
    }
    public static long Parse(int v)
    {
        long tmp = v;
        return (long)(tmp * SPLIT_INT);
    }
    public static long Parse(double v)
    {
        double tmp = v;
        return (long)(tmp * SPLIT_DOUBLE);
    }
    public static double ToDouble(long v)
    {
        return (double)v / SPLIT_DOUBLE;
    }
    public static int ToInt(long v)
    {
        return (int)(v / SPLIT_LONG);
    }
    public static float ToFloat(long v)
    {
        return (float)ToDouble(v);
    }
    public static double ToDouble(Decimal v)
    {
        return (double)v.value / SPLIT_DOUBLE;
    }
    public static int ToInt(Decimal v)
    {
        return (int)(v.value / SPLIT_LONG);
    }
    public static double ToFloat(Decimal v)
    {
        return (float)ToDouble(v);
    }
}

